package com.qining618.cms.ucenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qining618.cms.ucenter.domain.User;
import com.qining618.cms.ucenter.mapper.UserMapper;
import com.qining618.cms.ucenter.service.AdminService;
import com.qining618.cms.ucenter.service.RoleService;
import com.qining618.common.exception.BusinessException;
import com.qining618.common.result.ErrorCode;
import com.qining618.common.utils.Query;
import com.qining618.common.utils.time.ClockUtil;
import com.qining618.common.utils.time.DateUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * 管理员 服务实现类
 * @author flt
 * @date 2019-09-20
 */
@Transactional(readOnly = true, rollbackFor = Exception.class)
@Service
public class AdminServiceImpl extends ServiceImpl<UserMapper, User> implements AdminService {

    @Autowired
    private RoleService roleService;

    @Override
    public IPage<User> page(Map<String, Object> params) {
        return this.baseMapper.pageAdmin(Query.of(params), params);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public User add(String nickname, String username, String password, Long roleId) {
        boolean isExist = this.baseMapper.existByUsername(username);
        if (isExist) {
            throw new BusinessException(ErrorCode.DATA_CONFLICT, "用户名已存在");
        }

        isExist = roleService.existById(roleId);
        if (!isExist) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "角色不存在");
        }

        User user = new User();
        user.setNickname(nickname);
        user.setUsername(username);
        user.setPassword(DigestUtils.md5Hex(password));
        user.setIsAdmin(true);
        user.setRoleId(roleId);

        int opNum = this.baseMapper.insert(user);
        if (opNum != 1) {
            throw new BusinessException(ErrorCode.DB_ERROR);
        }
        return user;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public User modify(Long id, String nickname, String username, Long roleId) {
        User user = this.baseMapper.selectById(id);
        if (user == null || !user.getIsAdmin()) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND);
        }

        boolean isExist = roleService.existById(roleId);
        if (!isExist) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "角色不存在");
        }

        if (!Objects.equals(username, user.getUsername())) {
            isExist = this.baseMapper.existByUsername(username);
            if (isExist) {
                throw new BusinessException(ErrorCode.DATA_CONFLICT, "用户名已存在");
            }
        }

        User upUser = new User();
        upUser.setId(id);
        upUser.setNickname(nickname);
        upUser.setUsername(username);
        upUser.setRoleId(roleId);

        int opNum = this.baseMapper.updateById(upUser);
        if (opNum != 1) {
            throw new BusinessException(ErrorCode.DB_ERROR);
        }
        return this.baseMapper.selectById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void resetPassword(Long id, String password) {
        User user = this.baseMapper.selectById(id);
        if (user == null || !user.getIsAdmin()) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND);
        }

        User upUser = new User();
        upUser.setId(user.getId());
        upUser.setPassword(DigestUtils.md5Hex(password));
        int opNum = this.baseMapper.updateById(upUser);
        if (opNum != 1) {
            throw new BusinessException(ErrorCode.DB_ERROR);
        }
    }

    @Override
    public User findByUsername(String username) {
        return this.baseMapper.selectOne(new QueryWrapper<User>()
                .lambda()
                .eq(User::getUsername, username)
                .eq(User::getIsAdmin, true));
    }

    @Override
    public User findById(Long userId) {
        return this.baseMapper.selectOne(new QueryWrapper<User>()
                .lambda()
                .eq(User::getId, userId)
                .eq(User::getIsAdmin, true));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateLoginSuccess(Long userId, String ip) {
        Date date = ClockUtil.currentDate();
        int opNum = this.baseMapper.updateLoginSuccess(userId, date, ip);
        if (opNum != 1) {
            throw new BusinessException(ErrorCode.DB_ERROR);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateLoginError(Long userId, String ip) {
        Date date = ClockUtil.currentDate();
        // 获取用户信息
        User user = this.baseMapper.selectById(userId);

        // 要更新的信息
        User upUser = new User();
        upUser.setId(userId);
        upUser.setErrorCount((short) (user.getErrorCount() + 1));
        upUser.setErrorTime(date);
        upUser.setErrorIp(ip);

        // 错误超过4次 锁定账号
        if (upUser.getErrorCount() > 4) {
            upUser.setLockTime(date);
            upUser.setIsLock(true);
            upUser.setLockDueTime(DateUtil.addHours(date,user.getErrorCount() - 4));
        }
        int opNum = this.baseMapper.updateById(upUser);
        if (opNum != 1) {
            throw new BusinessException(ErrorCode.DB_ERROR);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void freeze(Long userId, Date dueTime, String reason) {
        User upUser = new User();
        upUser.setId(userId).setIsFreeze(true).setFreezeTime(new Date()).setFreezeDueTime(dueTime).setFreezeReason(reason);
        int opNum = this.baseMapper.updateById(upUser);
        if (opNum != 1) {
            throw new BusinessException(ErrorCode.DB_ERROR);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void unFreeze(Long userId) {
        int opNum = this.baseMapper.unFreeze(userId);
        if (opNum != 1) {
            throw new BusinessException(ErrorCode.DB_ERROR);
        }
    }
}
